package com.myimooc.shiro.test.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @className: CustomRealm
 * @description: 自定义Realm
 * @date: 2020/5/12
 * @author: cakin
 */
// 仿照jdbcRealm继承 AuthorizingRealm
public class CustomRealm extends AuthorizingRealm {
    /**
     * 在map中放权限数据，模拟数据库
     */
    private Map<String, String> userMap = new HashMap<>();

    {
        userMap.put("Mark", "283538989cef48f3d7d8a1c1bdf2008f");
        super.setName("customRealm");
    }

/**
 * 功能描述：授权
 *
 * @author cakin
 * @date 2020/5/12
 * @param principals 主要是从中取得用户姓名
 * @return AuthorizationInfo 认证信息，里面封装了角色和权限信息
 */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals ) {
        String userName = (String) principals.getPrimaryPrincipal();
        // 通过用户名获取角色数据
        Set<String> roles = getRolesByUserName(userName);
        // 通过用户名获取权限数据
        Set<String> permissions = getPermissionsByUserName(userName);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    /**
     * 模拟从数据库或缓存中获取权限数据，某用户管关联的权限
     *
     * @param userName 用户名
     * @return 权限数据
     */
    private Set<String> getPermissionsByUserName( String userName ) {
        Set<String> permissions = new HashSet<>();
        permissions.add("user:delete");
        permissions.add("user:add");
        return permissions;
    }

    /**
     * 模拟从数据库或缓存中获取角色数据，某用户管理的角色
     *
     * @param userName 用户名
     * @return 角色数据
     */
    private Set<String> getRolesByUserName( String userName ) {
        Set<String> roles = new HashSet<>();
        roles.add("admin");
        roles.add("user");
        return roles;
    }

    /**
     * 认证
     *
     * @param token 主体传送过来的认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token ) throws AuthenticationException {
        // 获取用户名
        String userName = (String) token.getPrincipal();
        // 通过用户名到数据库中获取凭证
        String password = getPasswordByUserName(userName);
        if (password == null) {
            return null;
        }
        // 从数据库查询得到的认证信息，封装到authenticationInfo中
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("Mark", password, "customRealm");
        authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("Mark"));
        return authenticationInfo;
    }

    /**
     * 模拟数据库查询凭证
     *
     * @param userName 用户名
     * @return 凭证
     */
    private String getPasswordByUserName( String userName ) {
        // 实际开发中需访问数据库
        return userMap.get(userName);
    }

    public static void main( String[] args ) {
        Md5Hash md5Hash = new Md5Hash("123456", "Mark");
        System.out.println(md5Hash.toString());
    }

}
